// src/components/renderFunctionComponents/RenderFunctionNode.ts
import { h, defineComponent, computed, type PropType, type CSSProperties, type VNode } from 'vue'; // Added VNode type
import { Handle, Position, type NodeProps } from '@vue-flow/core';
import type { UniversalFlowNodeData, NodeSemanticType } from '@/models/universalFlow';
import { useUniversalVisualizerSettingsStore } from '@/stores/universalVisualizerSettingsStore';
import { NodeToolbar } from '@vue-flow/node-toolbar'; // Import NodeToolbar
import appConfig from '@/config'; // Import appConfig
import { ElIcon, ElButton } from 'element-plus'; // Import ElButton
import { useUniversalEditorStore } from '@/stores/universalEditorStore'; // Import store
import { InfoFilled, Delete } from '@element-plus/icons-vue'; // Import icons
// Import color/styling utilities
import {
    semanticTypeColorCodes,
    levelColorPalette,
    jdfCoreTagColorCodes,
    defaultElementObjectColor
} from '@/config';
import tinycolor from 'tinycolor2';
import { ElMessageBox, ElMessage } from 'element-plus'; // Import ElMessageBox and ElMessage

// Define props interface matching UniversalNodeProps (if applicable)
interface RenderFunctionNodeProps extends NodeProps {
    data: UniversalFlowNodeData;
    // selected, position, etc. are inherited from NodeProps
}

// --- Helper Function (same as in UniversalNode.vue) ---
const truncate = (text: string | undefined, maxLength: number): string => {
    if (!text) return '';
    return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
};

// --- Estimated Height for Placeholder ---
const PLACEHOLDER_HEIGHT_PX = 18; // Adjust based on font-size, line-height, padding etc.

export default defineComponent({
    name: 'RenderFunctionNode',
    // RESTORE explicit props definition
    props: {
        // Inherited props from NodeProps that Vue Flow passes
        id: { type: String as PropType<string>, required: true },
        type: { type: String as PropType<string>, default: 'universal' },
        selected: { type: Boolean as PropType<boolean>, default: false },
        position: { type: Object as PropType<{ x: number; y: number }>, required: true },
        draggable: { type: Boolean as PropType<boolean>, default: undefined },
        selectable: { type: Boolean as PropType<boolean>, default: undefined },
        connectable: { type: Boolean as PropType<boolean>, default: undefined },
        // ... add others if needed (e.g., dragHandle, sourcePosition, targetPosition)
        
        // Custom data prop
        data: { type: Object as PropType<UniversalFlowNodeData>, required: true },
    },
    // Use the interface in setup signature for type safety inside
    setup(props: RenderFunctionNodeProps) {
        console.log(`[RenderFunctionNode] Setup executed for node ID: ${props.id}, Name: ${props.data?.name}`);

        const visualizerSettings = useUniversalVisualizerSettingsStore();
        const editorStore = useUniversalEditorStore(); 

        // --- Toolbar action handlers ---
        const handleShowDetails = () => {
            console.log("[RenderFunctionNode] Show details clicked for node:", props.id);
            editorStore.selectNodeForDrawer(props.id);
        };

        const handleDeleteNode = async () => {
            console.log(`[RenderFunctionNode] Delete requested for node: ${props.id}`);
            try {
                // ADD CONFIRMATION DIALOG
                await ElMessageBox.confirm(
                    `确定要删除节点 "${props.data.name || props.id}" 及其所有子节点吗？此操作不可逆。`,
                    '确认删除',
                    {
                        confirmButtonText: '确定删除',
                        cancelButtonText: '取消',
                        type: 'warning',
                    }
                );
                // If confirmed, proceed
                await editorStore.deleteNodeWithDescendants(props.id);
                ElMessage.success('节点已删除。'); // Provide feedback
            } catch (error) { 
                if (error !== 'cancel' && error !== 'close') {
                    console.error("Error deleting node from RenderFunctionNode:", error);
                    ElMessage.error(`删除节点失败: ${editorStore.error || '未知错误'}`);
                } else {
                    ElMessage.info('删除操作已取消。');
                }
            }
        };

        // --- Computed property for dynamic background color (copied from UniversalNode.vue) ---
        const nodeBackgroundColor = computed<string>(() => {
            const mode = visualizerSettings.coloringMode;
            const type = props.data.nodeSemanticType;
            const name = props.data.name;
            const level = props.data.level ?? 0;
            const format = props.data.format;
            const fallbackColor = defaultElementObjectColor;

            const adjustColorByLevel = (baseColor: string, currentLevel: number): string => {
                try {
                    const lightenAmount = Math.min(currentLevel * 3, 30);
                    return tinycolor(baseColor).lighten(lightenAmount).toString();
                } catch (e) {
                    console.error("Error adjusting color by level:", e);
                    return baseColor;
                }
            };

            const getJdfKeywordColor = (): string | undefined => {
                if (name && (format === 'xml' || format === 'unknown')) {
                    return jdfCoreTagColorCodes[name];
                }
                return undefined;
            };

            // ... (Placeholder getMetronKeywordColor) ...

            switch (mode) {
                case 'semantic':
                    return semanticTypeColorCodes[type] || fallbackColor;
                case 'level':
                    if (levelColorPalette.length > 0) {
                        const colorIndex = level % levelColorPalette.length;
                        return levelColorPalette[colorIndex];
                    } else {
                        return fallbackColor;
                    }
                case 'single-structure':
                    if (type === 'element' || type === 'object') {
                        return visualizerSettings.singleStructureColorValue || defaultElementObjectColor;
                    }
                    return semanticTypeColorCodes[type] || defaultElementObjectColor;
                case 'single-true':
                    if (type === 'root' && semanticTypeColorCodes['root']) {
                        return semanticTypeColorCodes['root'];
                    }
                    return visualizerSettings.trueSingleColorValue || '#d1d5db';
                case 'jdf-keyword':
                    if (type === 'element' || type === 'object') {
                        return getJdfKeywordColor() || defaultElementObjectColor;
                    }
                    return semanticTypeColorCodes[type] || fallbackColor;
                case 'jdf-keyword-level':
                    if (type === 'element' || type === 'object') {
                        const baseColor = getJdfKeywordColor() || defaultElementObjectColor;
                        return adjustColorByLevel(baseColor, level);
                    }
                    return semanticTypeColorCodes[type] || fallbackColor;
                 // ... (cases for metron-keyword, metron-keyword-level, custom-schema)
                 // ... (default case)
                default:
                    if (type === 'element' || type === 'object') {
                        const baseColor = getJdfKeywordColor() || defaultElementObjectColor;
                        return adjustColorByLevel(baseColor, level);
                    } else {
                        return semanticTypeColorCodes[type] || fallbackColor;
                    }
            }
        });

        // --- Computed property for dynamic text color (copied from UniversalNode.vue) ---
        const contrastingTextColor = computed<string>(() => {
            const bgColor = nodeBackgroundColor.value;
            if (!bgColor) return '#1f2937';
            try {
                return tinycolor(bgColor).isLight() ? '#1f2937' : 'white';
            } catch (e) {
                console.error("Error determining text color:", e);
                return '#1f2937';
            }
        });

        // --- REPLACE nodeStyle with the complete dynamic style ---
        const nodeStyle = computed((): CSSProperties => {
            return {
                border: `1px solid ${props.selected ? 'dodgerblue' : 'transparent'}`, // Use transparent border normally, blue when selected
                borderRadius: '4px',
                padding: '10px',
                backgroundColor: nodeBackgroundColor.value, // Use dynamic background
                color: contrastingTextColor.value, // Use dynamic text color
                minWidth: '150px', // Keep minimum width
                fontSize: '12px', 
                lineHeight: 1.4,
                position: 'relative', // Needed for handles
            };
        });

        // --- Attribute Display Logic Computeds (Mirrors UniversalNode.vue) ---
        const attributeEntries = computed(() => {
            return props.data.attributes ? Object.entries(props.data.attributes).map(([name, value]) => ({ name, value })) : [];
        });

        const attributeCount = computed(() => attributeEntries.value.length);

        const canShowAttributes = computed(() => {
            // Only elements/objects typically have attributes we want to show this way
            return (props.data.nodeSemanticType === 'element' || props.data.nodeSemanticType === 'object') && attributeCount.value > 0;
        });

        const attributesToDisplay = computed(() => {
            const mode = visualizerSettings.attributeDisplayMode;
            const allAttrs = attributeEntries.value;
            if (mode === 'first-1') return allAttrs.slice(0, 1);
            if (mode === 'first-3') return allAttrs.slice(0, 3);
            if (mode === 'all') return allAttrs; // Truncation happens during render
            return []; // For hide/count mode
        });

        const hasMoreAttributes = computed(() => {
            const mode = visualizerSettings.attributeDisplayMode;
            return (
                (mode === 'first-1' && attributeCount.value > 1) ||
                (mode === 'first-3' && attributeCount.value > 3)
            );
        });

        // Computed for the separator's style (if not 'none')
        const attributeSeparatorStyle = computed((): CSSProperties => {
            const styleType = visualizerSettings.attributeSeparatorStyle;
            if (styleType === 'none') {
                return {}; // No border needed
            }
            return {
                width: '100%',
                paddingTop: '6px', // Space above attributes
                marginTop: '6px', // Space below node name/content
                borderTop: `1px ${styleType} #ccc`, // Use styleType directly
                // Add dark mode consideration later if needed
            };
        });

        // --- Attribute Rendering Function (REVISED) ---
        const renderAttributes = (): VNode | null => {
            const mode = visualizerSettings.attributeDisplayMode;
            const normalize = visualizerSettings.normalizeAppearanceWithAttrs;
            const count = attributeCount.value;
            const showList = mode === 'first-1' || mode === 'first-3' || mode === 'all';
            const separatorStyle = visualizerSettings.attributeSeparatorStyle;

            const hasVisibleAttributes = (showList || mode === 'count') && count > 0;
            const needsNormalizationPlaceholder = normalize && !hasVisibleAttributes;
            const shouldRenderArea = hasVisibleAttributes || needsNormalizationPlaceholder;

            if (!shouldRenderArea) {
                return null; 
            }

            let contentVNode: VNode | VNode[] | string | null = null;
            if (mode === 'count' && count > 0) {
                contentVNode = h('span', { class: 'attribute-summary' }, `(Attrs: ${count})`);
            } else if (showList && count > 0) {
                const listItems = attributesToDisplay.value.map(attr =>
                    h('div', { class: 'attribute-item', key: attr.name }, [
                        h('span', { class: 'attr-name' }, `${attr.name}`),
                        '= ',
                        h('span', { class: 'attr-value', title: attr.value }, `"${truncate(attr.value, 15)}"`),
                    ])
                );
                if (hasMoreAttributes.value) {
                    listItems.push(h('span', { class: 'more-attrs' }, '...'));
                }
                contentVNode = h('div', { class: 'attribute-list' }, listItems);
            }

            const wrapperStyle: CSSProperties = {
                width: '100%',
                paddingTop: '6px',
                marginTop: '6px',
                boxSizing: 'border-box',
            };
            if (separatorStyle !== 'none') {
                wrapperStyle.borderTop = `1px ${separatorStyle} #ccc`;
            }
            if (needsNormalizationPlaceholder) {
                wrapperStyle.height = `${PLACEHOLDER_HEIGHT_PX}px`; 
            }

            // --- Create Wrapper VNode (FIXED Children Argument) --- 
            let children: VNode | VNode[] | string | undefined | null = undefined; // Default to undefined (no children)
            if (contentVNode) {
                children = contentVNode;
            } else if (needsNormalizationPlaceholder) {
                // Render an empty div as the child to ensure the wrapper with height is rendered
                children = h('div'); 
            }
            // If neither condition met, children remains undefined

            return h(
                'div',
                {
                    class: 'attribute-display-wrapper',
                    style: wrapperStyle,
                },
                children // Pass the calculated children (VNode, VNode[], string, or undefined)
            );
        };

        // --- UPDATED Computed Property for Node Label/Name display ---
        const nodeDisplayName = computed(() => {
          const name = props.data.name;
          const type = props.data.nodeSemanticType;
          const format = props.data.format;
          const displayMode = visualizerSettings.xmlTagNameDisplayMode;

          // Apply XML tag display mode if applicable
          if (name && format === 'xml' && type === 'element') {
            if (displayMode === 'openingTag') {
              return `<${name}>`;
            } else if (displayMode === 'closingTag') {
              return `</${name}>`;
            } // else 'nameOnly' or default
            return name;
          }

          // Fallback for non-XML elements or other types
          if (name) return name;
          if (type === 'array') return '[Array]';
          if (type === 'object') return '{Object}';
          if (type === 'comment') return 'Comment';
          // Specific label for value nodes (might be empty if value is shown separately)
          if (type === 'value') return ''; // Value shown in different div
          return `[${type || 'Unknown'}]`;
        });

        // --- NEW Computed Properties for Handle Positions (from previous step) ---
        const targetHandlePosition = computed(() => {
          const mode = visualizerSettings.handlePositionMode;
          const direction = visualizerSettings.layoutDirection;
          if (mode === 'top-bottom') return Position.Top;
          if (mode === 'left-right') return Position.Left;
          return direction === 'TB' ? Position.Top : Position.Left;
        });

        const sourceHandlePosition = computed(() => {
          const mode = visualizerSettings.handlePositionMode;
          const direction = visualizerSettings.layoutDirection;
          if (mode === 'top-bottom') return Position.Bottom;
          if (mode === 'left-right') return Position.Right;
          return direction === 'TB' ? Position.Bottom : Position.Right;
        });

        // --- Render Function (Ensure it's outside computed properties) --- 
        return () => {
            const nodeData = props.data;

            // --- Toolbar VNode definition --- 
            const toolbarVNode = h(NodeToolbar, 
                { 
                    isVisible: props.selected && appConfig.enableNodeToolbar, 
                    nodeId: props.id, 
                    position: Position.Top 
                },
                // Default slot content for buttons
                () => [
                    h(ElButton, { type: 'primary', size: 'small', icon: InfoFilled, circle: true, onClick: handleShowDetails, title: '查看详情' }),
                    h(ElButton, { type: 'danger', size: 'small', icon: Delete, circle: true, onClick: handleDeleteNode, title: '删除节点' })
                ]
            );

            // --- Children VNodes array ---
            const childrenVNodes = [
                 // Use dynamic handles
                 h(Handle, { type: 'target', position: targetHandlePosition.value, id: `${props.id}-target` }),
                 
                 // Use updated nodeDisplayName
                 h('div', { class: 'node-name' }, 
                    nodeDisplayName.value // Use computed value
                 ),
                 
                 // Value/Content rendering
                 nodeData.nodeSemanticType === 'value' && (nodeData.value !== undefined && nodeData.value !== null)
                     ? h('div', { class: 'node-value-content' }, String(nodeData.value)) 
                     : nodeData.content 
                         ? h('div', { class: 'node-content' }, nodeData.content) 
                         : null,
                 
                 renderAttributes(), // Render attributes

                 // Use dynamic handles
                 h(Handle, { type: 'source', position: sourceHandlePosition.value, id: `${props.id}-source` }),
                 toolbarVNode
            ];
            const finalChildren = childrenVNodes.filter(vnode => vnode !== null);

            // --- Main Node VNode ---
            return h(
                'div',
                {
                    class: ['render-function-node', { selected: props.selected }],
                    style: nodeStyle.value, // Apply computed style
                },
                finalChildren // Pass the filtered children
            );
        }; // <-- END of the returned render function
    }, // <-- END of setup function
});